package com.xdf.whiteaccount.aop;

import com.xdf.whiteaccount.config.FlywayConfig;
import com.xdf.whiteaccount.config.properties.DbConfig;
import com.xdf.whiteaccount.config.datasource.DynamicDataSource;
import com.xdf.whiteaccount.enums.DatasourceKey;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @program: white-account
 * @description: 动态切换数据源
 * @author: 张柯
 * @create: 2021-06-11 10:24
 **/
@Aspect
@Slf4j
@Component
public class DynamicDataSourceAspect {
    @Autowired
    private DbConfig dbConfig;
    @Autowired
    private FlywayConfig flywayConfig;

    @Pointcut("execution(* com.xdf.whiteaccount.service.impl.*.*(..))")
    private void localDs() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.controller.*.*(..))")
    private void localControllerDs() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.cloudcontroller.*.*(..))")
    private void cloudControllerDs() {
    }

    @Pointcut("execution(* com.xdf.whiteaccount.cloudservice.impl.*.*(..))")
    private void cloudDs() {
    }

    /**
     * 连接每个客户数据源
     */
    @Before("localControllerDs()")
    public void beforeController() {
        DynamicDataSource dataSource = DynamicDataSource.getInstance();
        setDataSource(dataSource);
    }

    /**
     * 连接主数据源
     */
    @Before("cloudControllerDs()")
    public void beforeCloudController() {
        DynamicDataSource dataSource = DynamicDataSource.getInstance();
        dataSource.switchDefault();
    }


    /**
     * 主数据源
     *
     * @param proceedingJoinPoint
     * @throws Throwable
     */
    @Around("cloudDs()")
    public Object aroundCloud(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        DynamicDataSource dataSource = DynamicDataSource.getInstance();
        String key = dataSource.getCurrentDataSourceName();
        dataSource.switchDefault();
        Object o = proceedingJoinPoint.proceed();
        dataSource.switchDataSource(key);
        return o;
    }

    /**
     * 注入从数据源
     *
     * @param proceedingJoinPoint
     */
    @Around("localDs()")
    public Object aroundLocal(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        DynamicDataSource dataSource = DynamicDataSource.getInstance();
        String currentKey = dataSource.getCurrentDataSourceName();
        setDataSource(dataSource);
        Object o = proceedingJoinPoint.proceed();
        dataSource.switchDataSource(currentKey);
        return o;
    }

    private void setDataSource(DynamicDataSource dataSource) {
        String key;
        if (SecurityUtils.getSubject().isAuthenticated()) {
            key = String.valueOf(SecurityUtils.getSubject().getSession().getAttribute(DatasourceKey.CURRENT_DATASOURCE_KEY));
            dataSource.setStorageDatasource(key);
        } else {
            key = dataSource.getStorageDatasource();
        }
        if (!dataSource.switchDataSource(key)) {
            dbConfig.setName(key);
            dbConfig.setUrl(dbConfig.getJdbcUrl(key));
            if (dataSource.addAndSwitchDataSource(dbConfig)) {
                //  初始化事件,数据库版本更新
                log.debug("添加{}数据库成功!", key);
                log.warn("开始执行flyway");
                flywayConfig.migrate();
            }
        }
    }

    /**
     * 抛出异常后操作
     */
    @AfterThrowing("localDs()||cloudDs()")
    public void throwExc() {
        DynamicDataSource dataSource = DynamicDataSource.getInstance();
        dataSource.clearDataSource();
    }
}